package com.bolt.core.view.tag;

import com.bolt.common.utils.SpringContextUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.core.view.components.ComponentsBase;
import com.bolt.core.view.config.PageRepository;
import com.bolt.core.view.config.UIProperties;
import com.bolt.core.view.templates.FreemarkerTemplateEngine;
import org.springframework.beans.BeansException;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.DynamicAttributes;
import java.util.HashMap;
import java.util.Map;


public abstract class TemplateBodyTagSupport extends BodyTagSupport implements DynamicAttributes {

    private static final long serialVersionUID = 1L;


    protected String name;


    protected String template;

    protected String theme;

    protected String templateDir;

    protected ComponentsBase component;

    protected UIProperties getUiProperties(){
        return SpringContextUtil.getBean(UIProperties.class);
    }

    protected FreemarkerTemplateEngine getFreemarkerTemplateEngine(){
        return SpringContextUtil.getBean(FreemarkerTemplateEngine.class);
    }

    @Override
    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setTemplate(String template) {
        this.template = template;
    }

    public void setTheme(String theme) {
        this.theme = theme;
    }

    public void setTemplateDir(String templateDir) {
        this.templateDir = templateDir;
    }

    public String getName() {
        return name;
    }

    public String getTemplate() {
        return template;
    }

    public String getTheme() {
        return theme;
    }

    public String getTemplateDir() {
        return templateDir;
    }


    public ComponentsBase getComponent() {
        return this.component;
    }

    @Override
    public void setDynamicAttribute(String uri, String localName, Object value) throws JspException {
        dynamicAttributes.put(localName, value);
    }


    protected Map <String, Object> dynamicAttributes = new HashMap <>();


    public TemplateBodyTagSupport() {
        super();
    }

    protected String getWebPath() {
        String path = getRequest().getContextPath();
        String basePath = getRequest().getScheme() + "://" + getRequest().getServerName() + ":" + getRequest().getServerPort() + path + "/";
        return basePath;
    }


    public abstract ComponentsBase getUI();

    public HttpServletRequest getRequest() {
        return (HttpServletRequest) pageContext.getRequest();
    }

    public HttpServletResponse getResponse() {
        return (HttpServletResponse) pageContext.getResponse();
    }

    protected PageRepository getPageRepository() {
        PageRepository pageRepository = SpringContextUtil.getBean(PageRepository.class);
        return pageRepository;
    }

    protected Object getBean(String name) throws BeansException {
        Assert.hasText(name, "name must not be null!");
        return SpringContextUtil.getBean(name);
    }


    @Override
    public int doStartTag() throws JspException {
        component = getUI();
        evaluateExpressions();
        populateParams();
        component.start(getRequest(), getResponse(), pageContext.getOut());
        return EVAL_BODY_INCLUDE;
    }

    @Override
    public int doEndTag() throws JspException {

        component.end(getRequest(), getResponse(), pageContext.getOut());
        return EVAL_PAGE;
    }

    protected void evaluateExpressions() throws JspException {
        String string = null;
        if ((string = EvalHelper.evalString("id", getId(), this, pageContext)) != null) {
            setId(string);
        }

        if ((string = EvalHelper.evalString("template", getTemplate(), this, pageContext)) != null) {
            setTemplate(string);
        }

        if ((string = EvalHelper.evalString("templateDir", getTemplateDir(), this, pageContext)) != null) {
            setTemplateDir(string);
        }

        if ((string = EvalHelper.evalString("theme", getTheme(), this, pageContext)) != null) {
            setTheme(string);
        }


    }

    protected void populateParams() {
        component.setId(id);
        component.setName(name);
        UIProperties uiProperties = getUiProperties();
        if (StrUtil.isNotBlank(templateDir)) {
            component.setTemplateDir(templateDir);
        }else{
            component.setTemplateDir(uiProperties.getDefaultPath());
        }
        if (StrUtil.isNotBlank(theme)) {
            component.setTheme(theme);
        }else{
            component.setTheme(uiProperties.getTheme());
        }
        if (StrUtil.isNotBlank(template)) {
            component.setTemplate(template);
        }
        component.setTemplateEngine(getFreemarkerTemplateEngine());
        component.addAllParameters(dynamicAttributes);
    }


}
